
DATA   SEGMENT 
STARTMSG DB "[0] save the input data, [1] print all goods and num , [2] search for the corresponding quantity of the item", '$'
STRALL DB "Below is the full range of goods:",'$'                             
SELECT DB "Please input a goods, such as 'apple': ",'$'
INPUT  DB  "Please input a goods and num, such as 'apple,3': ",'$'
ERROR DB "ERROR",'$'
CRLF   DB  0AH, 0DH,'$'                   

; 0 - 1 - 2
INPUTNUM DB 20
        DB ?
        DB 40 DUP(0)

;一个 BUFFER 是 22个偏移
BUFFER DB  20				    ;预定义20字节的空间
       DB  ?				    ;待输入完成后，自动获得输入的字符个数
       DB  40  DUP(0) 
BUFFERS DB 50 DUP(20, ?, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)   
       DB '`'  ;数据段结尾标识符



DATA   ENDS                                  
STACK  SEGMENT   STACK                       
       DW  100  DUP(0)                      
STACK  ENDS                                  
CODE   SEGMENT
ASSUME CS:CODE, DS:DATA, SS:STACK


;另取一行   
printEnter:
        LEA DX, CRLF                                         
        MOV AH, 09H							 
        INT 21H
        RET

;输入并且保存如data段 BUFFERS标段
;(BUFFERS -> 保存数据段的基址, BX -> 保存si寄存器的偏移)
inputForData:
        PUSH DX
        PUSH AX
        PUSH SI
        ;打印提示输入信息
        LEA DX, INPUT           
        MOV AH, 09H							 
        INT 21H
        ;接收字符串
        LEA DX, DS:[BUFFERS+BX]                        
        MOV AH, 0AH
        INT 21H

        ;对字符串进行处理,在后面加一个$
        MOV AL, DS:[BUFFERS+1+BX]  ;第二位是字符串的个数                     
        ADD AL, 2
        MOV AH, 0
        MOV SI, AX      ; ax寄存器是16位置 -> 由ah+al组成
        MOV DS:[BUFFERS+SI+BX], '$'
        CALL printEnter

        ;输出输入的字符串
        ;LEA DX, DS:[BUFFERS+2+BX] ;第三位之后是字符串               
        ;MOV AH, 09H							 
        ;INT 21H
        ;CALL printEnter
        
       ;设置循环次数,为字符串长度
       ;初始化DI寄存器
        DEC SI
        DEC SI 
        MOV CX, SI      ;DS:[BUFFERS+1+BX] asdfsa
        MOV SI, 0       ;字符串偏移使用的寄存器
        ;判断这个字符串里面有没有 “,” 号 ,有就是0 没有就是1
        MOV AL, ','     ;设置 ',' 为终止

L2:     mov DL, DS:[BUFFERS+2+BX+SI]        
        CMP AL, DL
        JZ L2INPUTEXIT
        INC SI
        LOOP L2
        JMP INPUTERROR
;L2TRUE:
        ;MOV CL, 0
        ;CMP CL , 1
INPUTERROR: ;输入格式错误
        LEA DX, ERROR           
        MOV AH, 09H							 
        INT 21H
        call printEnter

        ;发现错误 直接退出
        JMP EXIT
;        ;初始化SI寄存器
;        MOV SI, 0
;INPUTERRORL1:        
;        ;赋值0 清空区域
;        MOV DS:[BUFFERS + SI + BX], 0
;        CMP SI, 22
;        JZ L2INPUTEXIT
;        INC SI
;        JMP INPUTERRORL1



L2INPUTEXIT:
        POP DX
        POP AX
        POP SI
        ret


;实现查询功能，输入的字符串保存在BUFFER , 并且在BUFFERS数据段里面进行查询
;遍历整个BUFFERS数据段，观察有没有相同的字符串，有的话就输出
;（匹配条件，字符串本身是否一致;超过了输入字符串本身的长度视为查找失败）
;如果没有查询到，什么都不输出，如果查询到了输出对应的字符串
;1\dl->(inputStrNumber)-->cx  2\al->(selectStrChar) 3\dl->(inputStrChar) 4\SI.DI->(Str偏移) 
selectInputForOutPrintNum:
        PUSH SI
        PUSH DI
        PUSH DX
        PUSH CX
        PUSH AX
        ;打印提示输入信息
        LEA DX, SELECT           
        MOV AH, 09H							 
        INT 21H

        ;接收字符串
        LEA DX, DS:[BUFFER]                        
        MOV AH, 0AH
        INT 21H
        ;对字符串进行处理,在后面加一个$
        MOV AL, DS:[BUFFER+1]  ;第二位是字符串的个数                     
        ADD AL, 2
        MOV AH, 0
        MOV SI, AX      ; ax寄存器是16位置 -> 由ah+al组成
        MOV DS:[BUFFER+SI], '$'
        CALL printEnter
selectStr: 
        ;初始化字符串偏移寄存器
        ;SI寄存器用于对表的数据偏移， DI寄存器用于字符比较偏移
        MOV SI, 0
        MOV DI, 0
selectStrL1:     
        ;遍历保存数据的数据段
        MOV DL, DS:[BUFFERS+SI]        
        MOV AL, '`'  ;设置 ` 为终止
        CMP AL, DL
        JZ selectStrExit
        
        ;下面就是关于判断字的逻辑了
        ;拿着输入的字符串的每一个,去跟表里面的数据进行对比
        MOV CX, 0       ;初始化cx寄存器
selectStrL2:
        ;设置好 字偏移寄存器
        MOV DI, CX
        MOV AL, DS:[BUFFER+2+DI] ;DS:[BUFFERS+2+SI] 地址存放了起始字符串的偏移        
        ;ADD AL, 2
        ADD DI, SI
        MOV DL, DS:[BUFFERS+2+DI]
  
        ;比较 字 是否相等
        INC CX
        CMP DL, AL
        JZ selectStrL2

        DEC CX
        ;AX -> Input Str Number = [address+2]
        MOV AL, DS:[BUFFER+1]  ;获取输入寄存器的个数,放到ax寄存器里面去                     
        ;ADD AL, 2      ;不需要偏移两位，只需要获取寄存器的个数
        MOV AH, 0       ;ax寄存器是16位置 -> 由ah+al组成
        CMP CX, AX       ;判断是不是到字符串的最后一位了，如果到了就说明前面的字符都对的上
        JZ selectStrL2True1 

selectStrL2Exit:
        ADD SI, 22 ;调整字符串偏移, 到下一个字符串的起始位
        JMP selectStrL1 ;死循环，如果没到表数据的结尾就循环
selectStrExit:
selectInputForOutPrintNumExit:
        POP SI
        POP DI
        POP DX
        POP CX
        POP AX
        RET
selectStrL2True1:  
        ;防止出现 select:ap  input:a 的情况 , 使用输入字符串的长度去匹配select的最后一位是否为 ","
        ;不相等则回去继续比较下一个表的字段, 相等就说明查找成功
        MOV DI, AX
        ADD DI, SI
        MOV DL, DS:[BUFFERS+2+DI] ;看是不是 , 号

        MOV AX, 0
        MOV AL, ','
        ;最后一位都相等则说明就是对应的字符串
        CMP DL, AL
        JZ selectInputForOutPrintNumPrint        
        JMP selectInputForOutPrintNumExit
selectInputForOutPrintNumPrint: ;输查询到的字符串
        LEA DX, DS:[BUFFERS+2+SI]
        MOV AH, 09H
        INT 21H
        JMP selectInputForOutPrintNumExit


;打印所有的字符串出来
printAllStr:
        PUSH DX
        PUSH SI
        PUSH AX
        ;打印提示信息
        LEA DX, STRALL           
        MOV AH, 09H							 
        INT 21H
        CALL printEnter

        ;初始化寄存器
        MOV SI , 0 ;用于字符串偏移的寄存器
printAllStrL1:
        MOV AL, '~' ;全部打印的 标识符跟查询的不一样
        MOV DL, DS:[SI + BUFFERS]
        CMP AL, DL
        JZ printAllStrExit
        LEA DX, DS:[SI + BUFFERS + 2]
        MOV AH, 09H
        INT 21H
        CALL printEnter
        ADD SI, 22
        JMP printAllStrL1

printAllStrExit:
        POP DX 
        POP SI 
        POP AX
        RET

START:                                       
        MOV AX, DATA                         
        MOV DS, AX       

        ;初始化bx寄存器
        MOV BX, 0
        
        ;CALL inputForData
        ;ADD BX, 22
        ;MOV DS:[BX+BUFFERS], '`' ;设置结尾符号
        ;
        ;CALL printEnter
;
        ;CALL selectInputForOutPrintNum
;
        ;CALL printEnter
;
        ;CALL printAllStr
W:
        CALL printEnter
        ;输出提示信息
        LEA DX, STARTMSG
        MOV AH, 09H
        INT 21H
        CALL printEnter

        ;接收字符串
        LEA DX, DS:[INPUTNUM]                        
        MOV AH, 0AH
        INT 21H
       
        ;判断是不是0
        MOV DL , DS:[INPUTNUM+2]
        MOV AL , '0'
        CMP DL , AL
        JZ START0

        ;判断是不是1
        MOV DL , DS:[INPUTNUM+2]
        MOV AL , '1'
        CMP DL , AL
        JZ START1

        ;判断是不是2
        MOV DL , DS:[INPUTNUM+2]
        MOV AL , '2'
        CMP DL , AL
        JZ START2

        ;输入其他的退出
        JMP EXIT

START0:
        CALL inputForData
        ADD BX, 22
        JMP W
START1:
        ;MOV DS:[BX+BUFFERS], ''
        MOV DL, DS:[BX+BUFFERS] 
        MOV DS:[BX+BUFFERS], '~' ;设置结尾符号
        CALL printAllStr
        MOV DS:[BX+BUFFERS], DL
        ;MOV BX, 22
        ;call inputForData
        JMP W

START2:
        CALL selectInputForOutPrintNum
        JMP W
 



EXIT:   MOV AH, 4CH                          ;返回DOS系统
        INT 21H
CODE   ENDS                                  
END    START 